<?php
/**
 * Created by PhpStorm.
 * User: Celebration-Grey
 * Date: 2017/4/14
 * Time: 16:09
 */

namespace App\Http\Classes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;

class Email
{
    private $email;
    private $code;
    private $isLock;
    private $prefix = [
        'register' => 'e_register_',
        'reset'    => 'e_reset_',
        'lock'     => 'e_lock_',
        'token'    => 'r_t_'
    ];
    private $lockKey;
    private $registerKey;
    private $resetKey;
    private $resetToken;
    private $message = array(
        0   =>  '请勿频繁操作',
        1   =>  '邮件服务器发送邮件失败',
        2   =>  '未知错误'
    );
    private $error = 2;

    public function __construct($email = '')
    {
        $this->email = $email;
        $this->setKeys();
        $this->validatorLock();
    }

    private function setKeys()
    {
        $this->lockKey      = $this->prefix['lock'] . $this->email;
        $this->registerKey  = $this->prefix['register'] . $this->email;
        $this->resetKey     = $this->prefix['reset'] . $this->email;
    }

    private function addLock()
    {
        Redis::set( $this->lockKey, true );
        Redis::expire( $this->lockKey, 60 );
    }

    private function createCode()
    {
        $this->code = Common::getRand();
    }

    private function saveCode()
    {
        Redis::set( $this->registerKey, $this->code );
        Redis::expire ( $this->registerKey, 60 * 60 * 2 );
    }

    public function sendRegisterEmail()
    {
        if ( !$this->isLock )
        {
            $this->createCode();
            $this->saveCode();
            $email = $this->email;
            $flag = Mail::send('emails.verification',
                ['code' => $this->code ],
                function($message) use ($email){
                    $message ->to($email)->subject('英语小网站注册通知邮件');
                });
            if($flag){
                $this->addLock();
                return true;
            }
            else{
                $this->error = 1;
                return false;
            }
        }
        else
        {
            $this->error = 0;
            return false;
        }
    }

    private function validatorLock()
    {
        if ( Redis::exists( $this->lockKey ) )
        {
            $this->isLock = true;
        }
        else
        {
            $this->isLock = false;
        }
    }

    public function validatorCode( $code = null )
    {
        $redisCode = Redis::get( $this->registerKey );

        if ( $redisCode == $code && $code !== null )
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    private function createResetToken()
    {   
        $this->resetToken = hash('md5', Common::getRand());
    }

    private function saveResetToken()
    {
        $create_at = time();
        $expired_at = $create_at + 7200;
        $data = array(
            'token'         =>      $this->resetToken,
            'email'         =>      $this->email,
            'id'            =>      Common::getUserIdByEmail( $this->email ),
            'ip'            =>      $_SERVER['REMOTE_ADDR'],
            'type'          =>      'reset',
            'create_at'     =>      $create_at,
            'expired_at'    =>      $expired_at
        );
        Redis::set( $this->prefix['token'] . $this->resetToken, json_encode($data) );
        Redis::expire( $this->prefix['token'] . $this->resetToken, 7200 );
    }

    public function sendResetEmail()
    {
        if ( ! $this->isLock )
        {
            $this->createResetToken();
            $this->saveResetToken();
            $email = $this->email;
            $link = 'http://' . $_SERVER['HTTP_HOST'] . '/reset?_token=' . $this->resetToken;
            $flag = Mail::send('emails.reset',
                ['link' => $link ],
                function($message) use ($email){
                    $message ->to($email)->subject('英语小网站修改密码通知邮件');
                });
            if( $flag ){
                $this->addLock();
                return true;
            }
            else{
                $this->error = 1;
                return false;
            }
        }
        else
        {
            $this->error = 0;
            return false;
        }
    }

    public function getMessage()
    {
        return $this->message[ $this->error ];
    }
}